<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title th:text="${title} + ' - FTP管理系统'">日志管理 - FTP管理系统</title>

    <!-- Bootstrap CSS -->
    <link th:href="@{/webjars/bootstrap/5.3.0/css/bootstrap.min.css}" rel="stylesheet">
    <!-- Font Awesome -->
    <link href="https://witmore.oss-cn-hangzhou.aliyuncs.com/cdn/npm/font-awesome/6.7.2/all.min.css" rel="stylesheet">
    <!-- Custom CSS -->
    <link th:href="@{/css/admin.css}" rel="stylesheet">
</head>
<body>
    <div id="app">
        <div class="admin-layout">
            <!-- 左侧边栏 -->
            <div class="sidebar">
                <div class="sidebar-brand">
                    <h4><i class="fas fa-server me-2"></i>FTP管理系统</h4>
                </div>
                <ul class="sidebar-menu">
                    <li>
                        <a href="/admin">
                            <i class="fas fa-tachometer-alt"></i>仪表盘
                        </a>
                    </li>
                    <li>
                        <a href="/admin/users">
                            <i class="fas fa-users"></i>用户管理
                        </a>
                    </li>
                    <li>
                        <a href="/admin/logs" class="active">
                            <i class="fas fa-list-alt"></i>操作日志
                        </a>
                    </li>
                    <li>
                        <a href="/admin/connections">
                            <i class="fas fa-plug"></i>连接管理
                        </a>
                    </li>
                    <li>
                        <a href="/admin/monitor">
                            <i class="fas fa-chart-line"></i>系统监控
                        </a>
                    </li>
                </ul>
            </div>

            <!-- 主内容区域 -->
            <div class="main-content">
                <!-- 顶部导航栏 -->
                <div class="top-navbar">
                    <h1 class="page-title">操作日志</h1>
                    <nav aria-label="breadcrumb">
                        <ol class="breadcrumb">
                            <li class="breadcrumb-item"><a href="/admin">首页</a></li>
                            <li class="breadcrumb-item active">操作日志</li>
                        </ol>
                    </nav>
                </div>

                <!-- 内容区域 -->
                <div class="content-wrapper">
                    <!-- 页面操作按钮 -->
                    <div class="d-flex justify-content-between align-items-center mb-4">
                        <div></div>
                        <div class="btn-group">
                            <button class="btn btn-outline-primary" @click="loadLogs">
                                <i class="fas fa-sync-alt me-2"></i>刷新
                            </button>
                            <button class="btn btn-outline-success" @click="exportLogs">
                                <i class="fas fa-download me-2"></i>导出
                            </button>
                        </div>
                    </div>

            <!-- 搜索和筛选 -->
            <div class="card mb-4">
                <div class="card-body">
                    <div class="row mb-3">
                        <div class="col-md-3">
                            <div class="input-group">
                                <span class="input-group-text"><i class="fas fa-user"></i></span>
                                <input type="text" class="form-control" placeholder="搜索用户名..."
                                       v-model="searchForm.username" @keyup.enter="loadLogs">
                            </div>
                        </div>
                        <div class="col-md-3">
                            <select class="form-select" v-model="searchForm.operationType">
                                <option value="">全部操作</option>
                                <option value="UPLOAD">上传</option>
                                <option value="DOWNLOAD">下载</option>
                                <option value="DELETE">删除</option>
                                <option value="LIST">列表</option>
                            </select>
                        </div>
                        <div class="col-md-3">
                            <select class="form-select" v-model="searchForm.status">
                                <option value="">全部状态</option>
                                <option value="SUCCESS">成功</option>
                                <option value="FAILED">失败</option>
                            </select>
                        </div>
                        <div class="col-md-3">
                            <div class="input-group">
                                <span class="input-group-text"><i class="fas fa-file"></i></span>
                                <input type="text" class="form-control" placeholder="搜索文件名..."
                                       v-model="searchForm.fileName" @keyup.enter="loadLogs">
                            </div>
                        </div>
                    </div>
                    <div class="row mb-3">
                        <div class="col-md-3">
                            <div class="input-group">
                                <span class="input-group-text"><i class="fas fa-folder"></i></span>
                                <input type="text" class="form-control" placeholder="搜索文件路径..."
                                       v-model="searchForm.filePath" @keyup.enter="loadLogs">
                            </div>
                        </div>
                        <div class="col-md-3">
                            <div class="input-group">
                                <span class="input-group-text"><i class="fas fa-network-wired"></i></span>
                                <input type="text" class="form-control" placeholder="客户端IP..."
                                       v-model="searchForm.clientIp" @keyup.enter="loadLogs">
                            </div>
                        </div>
                        <div class="col-md-3">
                            <div class="input-group">
                                <span class="input-group-text"><i class="fas fa-calendar"></i></span>
                                <input type="datetime-local" class="form-control"
                                       v-model="searchForm.startTime" title="开始时间">
                            </div>
                        </div>
                        <div class="col-md-3">
                            <div class="input-group">
                                <span class="input-group-text"><i class="fas fa-calendar"></i></span>
                                <input type="datetime-local" class="form-control"
                                       v-model="searchForm.endTime" title="结束时间">
                            </div>
                        </div>
                    </div>
                    <div class="row">
                        <div class="col-md-12">
                            <div class="btn-group">
                                <button class="btn btn-primary" @click="loadLogs">
                                    <i class="fas fa-search me-1"></i>搜索
                                </button>
                                <button class="btn btn-outline-secondary" @click="resetSearch">
                                    <i class="fas fa-undo me-1"></i>重置
                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <!-- 日志列表 -->
            <div class="card">
                <div class="card-body">
                    <div class="table-responsive">
                        <table class="table table-hover">
                            <thead class="table-light">
                                <tr>
                                    <th>时间</th>
                                    <th>用户</th>
                                    <th>客户端IP</th>
                                    <th>操作类型</th>
                                    <th>文件名</th>
                                    <th>文件路径</th>
                                    <th>状态</th>
                                    <th>错误信息</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr v-for="log in logs" :key="log.id">
                                    <td>{{ formatDate(log.createTime) }}</td>
                                    <td>
                                        <i class="fas fa-user me-2"></i>{{ log.username }}
                                    </td>
                                    <td>
                                        <code>{{ log.clientIp }}</code>
                                    </td>
                                    <td>
                                        <span class="badge" :class="getOperationBadgeClass(log.operationType)">
                                            <i :class="getOperationIcon(log.operationType)" class="me-1"></i>
                                            {{ getOperationText(log.operationType) }}
                                        </span>
                                    </td>
                                    <td>
                                        <div v-if="isImageFile(log.fileName)" class="d-flex align-items-center">
                                            <i class="fas fa-image me-2 text-primary"></i>
                                            <span class="me-2">{{ log.fileName || '-' }}</span>
                                            <button class="btn btn-sm btn-outline-primary"
                                                    @click="previewImage(log)"
                                                    :disabled="log.status !== 'SUCCESS' || log.operationType !== 'UPLOAD'"
                                                    title="预览图片">
                                                <i class="fas fa-eye"></i>
                                            </button>
                                        </div>
                                        <div v-else>
                                            <i class="fas fa-file me-2"></i>{{ log.fileName || '-' }}
                                        </div>
                                    </td>
                                    <td>
                                        <code class="text-muted">{{ log.filePath || '-' }}</code>
                                    </td>
                                    <td>
                                        <span class="badge" :class="log.status === 'SUCCESS' ? 'bg-success' : 'bg-danger'">
                                            <i :class="log.status === 'SUCCESS' ? 'fas fa-check' : 'fas fa-times'" class="me-1"></i>
                                            {{ log.status === 'SUCCESS' ? '成功' : '失败' }}
                                        </span>
                                    </td>
                                    <td>
                                        <span v-if="log.errorMessage" class="text-danger" :title="log.errorMessage">
                                            {{ truncateText(log.errorMessage, 30) }}
                                        </span>
                                        <span v-else class="text-muted">-</span>
                                    </td>
                                </tr>
                                <tr v-if="logs.length === 0">
                                    <td colspan="8" class="text-center text-muted py-4">
                                        <i class="fas fa-inbox fa-2x mb-2"></i><br>
                                        暂无日志数据
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </div>

                    <!-- 分页组件 -->
                    <div v-if="pagination.total > 0" class="mt-4">
                        <div class="d-flex justify-content-end align-items-center flex-wrap">
                            <!-- 统计信息 -->
                            <div class="text-muted small me-4 mb-2">
                                <i class="fas fa-info-circle me-1"></i>
                                共 {{ pagination.total }} 条记录
                            </div>
                            
                            <!-- 每页显示选择器 -->
                            <div class="me-3 mb-2">
                                <label class="form-label mb-0 me-2 text-muted small">每页显示:</label>
                                <select class="form-select form-select-sm d-inline-block" 
                                        style="width: auto;" 
                                        v-model="pagination.size" 
                                        @change="changePageSize">
                                    <option value="10">10 条</option>
                                    <option value="20">20 条</option>
                                    <option value="50">50 条</option>
                                    <option value="100">100 条</option>
                                </select>
                            </div>
                            
                            <!-- 分页导航 -->
                            <nav v-if="pagination.pages > 1" class="mb-2">
                                <ul class="pagination pagination-sm mb-0">
                                    <!-- 首页 -->
                                    <li class="page-item" :class="{ disabled: pagination.current <= 1 }">
                                        <button class="page-link" 
                                                @click="changePage(1)" 
                                                :disabled="pagination.current <= 1"
                                                title="首页">
                                            <i class="fas fa-angle-double-left"></i>
                                        </button>
                                    </li>
                                    
                                    <!-- 上一页 -->
                                    <li class="page-item" :class="{ disabled: pagination.current <= 1 }">
                                        <button class="page-link" 
                                                @click="changePage(pagination.current - 1)" 
                                                :disabled="pagination.current <= 1"
                                                title="上一页">
                                            <i class="fas fa-angle-left"></i>
                                        </button>
                                    </li>
                                    
                                    <!-- 页码 -->
                                    <li class="page-item"
                                        v-for="page in getPageNumbers()"
                                        :key="page"
                                        :class="{ 
                                            active: page === pagination.current, 
                                            disabled: page === '...' 
                                        }">
                                        <button class="page-link"
                                                @click="page !== '...' ? changePage(page) : null"
                                                :disabled="page === '...'"
                                                :class="{ 'fw-bold': page === pagination.current }">
                                            {{ page }}
                                        </button>
                                    </li>
                                    
                                    <!-- 下一页 -->
                                    <li class="page-item" :class="{ disabled: pagination.current >= pagination.pages }">
                                        <button class="page-link" 
                                                @click="changePage(pagination.current + 1)" 
                                                :disabled="pagination.current >= pagination.pages"
                                                title="下一页">
                                            <i class="fas fa-angle-right"></i>
                                        </button>
                                    </li>
                                    
                                    <!-- 末页 -->
                                    <li class="page-item" :class="{ disabled: pagination.current >= pagination.pages }">
                                        <button class="page-link" 
                                                @click="changePage(pagination.pages)" 
                                                :disabled="pagination.current >= pagination.pages"
                                                title="末页">
                                            <i class="fas fa-angle-double-right"></i>
                                        </button>
                                    </li>
                                </ul>
                            </nav>
                            
                            <!-- 当只有一页时显示的信息 -->
                            <div v-else class="text-muted small mb-2">
                                <i class="fas fa-check-circle me-1 text-success"></i>
                                所有数据已显示完毕
                            </div>
                        </div>
                    </div>
                </div>
            </div>
                </div>
            </div>
        </div>
    </div>

    <!-- 图片预览模态框 -->
    <div class="modal fade" id="imagePreviewModal" tabindex="-1" aria-labelledby="imagePreviewModalLabel" aria-hidden="true">
        <div class="modal-dialog modal-lg">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title" id="imagePreviewModalLabel">
                        <i class="fas fa-image me-2"></i>图片预览 - {{ selectedLog.fileName }}
                    </h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body text-center">
                    <div v-if="imageLoading" class="d-flex justify-content-center">
                        <div class="spinner-border text-primary" role="status">
                            <span class="visually-hidden">加载中...</span>
                        </div>
                    </div>
                    <div v-else-if="imageError" class="alert alert-danger">
                        <i class="fas fa-exclamation-triangle me-2"></i>
                        图片加载失败：{{ imageError }}
                    </div>
                    <div v-else>
                        <img :src="imageUrl"
                             :alt="selectedLog.fileName"
                             class="img-fluid rounded shadow"
                             style="max-height: 500px;">
                        <div class="mt-3 text-muted">
                            <small>
                                <i class="fas fa-info-circle me-1"></i>
                                文件路径：{{ selectedLog.filePath }}<br>
                                上传时间：{{ formatDate(selectedLog.createTime) }}<br>
                                文件大小：{{ formatFileSize(selectedLog.fileSize) }}
                            </small>
                        </div>
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
                    <a v-if="!imageError && !imageLoading"
                       :href="imageUrl"
                       :download="selectedLog.fileName"
                       class="btn btn-primary">
                        <i class="fas fa-download me-2"></i>下载图片
                    </a>
                </div>
            </div>
        </div>
    </div>

    <!-- JavaScript Libraries -->
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script th:src="@{/webjars/bootstrap/5.3.0/js/bootstrap.bundle.min.js}"></script>

    <script>
        const { createApp } = Vue;

        createApp({
            data() {
                return {
                    logs: [],
                    searchForm: {
                        username: '',
                        operationType: '',
                        status: '',
                        fileName: '',
                        filePath: '',
                        clientIp: '',
                        startTime: '',
                        endTime: ''
                    },
                    pagination: {
                        current: 1,
                        size: 20,
                        total: 0,
                        pages: 0
                    },
                    selectedLog: {},
                    imageUrl: '',
                    imageLoading: false,
                    imageError: null
                }
            },
            mounted() {
                this.loadLogs();

                // 每30秒自动刷新
                setInterval(() => {
                    this.loadLogs();
                }, 30000);
            },
            methods: {
                async loadLogs() {
                    try {
                        const params = {
                            page: this.pagination.current,
                            size: this.pagination.size,
                            sortField: this.pagination.sortField || 'createTime',
                            sortOrder: this.pagination.sortOrder || 'DESC',
                            ...this.searchForm
                        };

                        // 过滤空值参数
                        Object.keys(params).forEach(key => {
                            if (params[key] === '' || params[key] === null || params[key] === undefined) {
                                delete params[key];
                            }
                        });

                        const response = await axios.get('/api/ftp/file-logs', { params });
                        if (response.data.code === 200) {
                            this.logs = response.data.records || [];

                            // 处理分页数据 - 兼容不同的响应格式
                            if (response.data.total !== undefined) {
                                this.pagination.total = response.data.total;
                            } else if (response.data.page && response.data.page.total !== undefined) {
                                this.pagination.total = response.data.page.total;
                            } else {
                                this.pagination.total = this.logs.length;
                            }

                            if (response.data.pages !== undefined) {
                                this.pagination.pages = response.data.pages;
                            } else if (response.data.page && response.data.page.totalPage !== undefined) {
                                this.pagination.pages = response.data.page.totalPage;
                            } else {
                                this.pagination.pages = Math.ceil(this.pagination.total / this.pagination.size);
                            }
                        }
                    } catch (error) {
                        console.error('加载日志失败:', error);
                        alert('加载日志失败');
                    }
                },
                resetSearch() {
                    this.searchForm = {
                        username: '',
                        operationType: '',
                        status: '',
                        fileName: '',
                        filePath: '',
                        clientIp: '',
                        startTime: '',
                        endTime: ''
                    };
                    this.pagination.current = 1;
                    this.loadLogs();
                },
                changePage(page) {
                    if (page >= 1 && page <= this.pagination.pages) {
                        this.pagination.current = page;
                        this.loadLogs();
                    }
                },
                changePageSize() {
                    this.pagination.current = 1;
                    this.loadLogs();
                },
                getPageNumbers() {
                    const pages = [];
                    const total = this.pagination.pages;
                    const current = this.pagination.current;

                    if (total <= 5) {
                        for (let i = 1; i <= total; i++) {
                            pages.push(i);
                        }
                    } else {
                        if (current <= 3) {
                            for (let i = 1; i <= 5; i++) {
                                pages.push(i);
                            }
                            if (total > 5) {
                                pages.push('...');
                                pages.push(total);
                            }
                        } else if (current >= total - 2) {
                            pages.push(1);
                            if (total > 5) {
                                pages.push('...');
                            }
                            for (let i = total - 4; i <= total; i++) {
                                pages.push(i);
                            }
                        } else {
                            pages.push(1);
                            pages.push('...');
                            for (let i = current - 1; i <= current + 1; i++) {
                                pages.push(i);
                            }
                            pages.push('...');
                            pages.push(total);
                        }
                    }

                    return pages;
                },
                formatDate(dateStr) {
                    if (!dateStr) return '';
                    return new Date(dateStr).toLocaleString('zh-CN');
                },
                getOperationBadgeClass(operation) {
                    switch (operation) {
                        case 'UPLOAD': return 'bg-primary';
                        case 'DOWNLOAD': return 'bg-success';
                        case 'DELETE': return 'bg-danger';
                        case 'LIST': return 'bg-info';
                        default: return 'bg-secondary';
                    }
                },
                getOperationIcon(operation) {
                    switch (operation) {
                        case 'UPLOAD': return 'fas fa-upload';
                        case 'DOWNLOAD': return 'fas fa-download';
                        case 'DELETE': return 'fas fa-trash';
                        case 'LIST': return 'fas fa-list';
                        default: return 'fas fa-question';
                    }
                },
                getOperationText(operation) {
                    switch (operation) {
                        case 'UPLOAD': return '上传';
                        case 'DOWNLOAD': return '下载';
                        case 'DELETE': return '删除';
                        case 'LIST': return '列表';
                        default: return operation;
                    }
                },
                truncateText(text, length) {
                    if (!text) return '';
                    return text.length > length ? text.substring(0, length) + '...' : text;
                },
                async exportLogs() {
                    try {
                        const params = {
                            ...this.searchForm,
                            page: 1,
                            size: 10000 // 导出更多数据
                        };

                        const response = await axios.get('/api/ftp/file-logs', { params });
                        if (response.data.code === 200) {
                            const logs = response.data.records || [];
                            this.downloadCSV(logs);
                        }
                    } catch (error) {
                        console.error('导出日志失败:', error);
                        alert('导出日志失败');
                    }
                },
                downloadCSV(logs) {
                    const headers = ['时间', '用户', '客户端IP', '操作类型', '文件名', '文件路径', '状态', '错误信息'];
                    const csvContent = [
                        headers.join(','),
                        ...logs.map(log => [
                            this.formatDate(log.createTime),
                            log.username,
                            log.clientIp,
                            this.getOperationText(log.operationType),
                            log.fileName || '',
                            log.filePath || '',
                            log.status === 'SUCCESS' ? '成功' : '失败',
                            log.errorMessage || ''
                        ].map(field => `"${field}"`).join(','))
                    ].join('\n');

                    const blob = new Blob(['\ufeff' + csvContent], { type: 'text/csv;charset=utf-8;' });
                    const link = document.createElement('a');
                    const url = URL.createObjectURL(blob);
                    link.setAttribute('href', url);
                    link.setAttribute('download', `ftp_logs_${new Date().toISOString().slice(0, 10)}.csv`);
                    link.style.visibility = 'hidden';
                    document.body.appendChild(link);
                    link.click();
                    document.body.removeChild(link);
                },
                isImageFile(fileName) {
                    if (!fileName) return false;
                    const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.svg', '.ico'];
                    const extension = fileName.toLowerCase().substring(fileName.lastIndexOf('.'));
                    return imageExtensions.includes(extension);
                },
                async previewImage(log) {
                    this.selectedLog = log;
                    this.imageLoading = true;
                    this.imageError = null;
                    this.imageUrl = '';

                    // 显示模态框
                    const modal = new bootstrap.Modal(document.getElementById('imagePreviewModal'));
                    modal.show();

                    try {
                        // 构建图片URL - 这里需要根据实际的文件访问路径调整
                        const imageUrl = `/api/ftp/file-preview?username=${encodeURIComponent(log.username)}&filePath=${encodeURIComponent(log.filePath)}`;

                        // 检查图片是否可以加载
                        const img = new Image();
                        img.onload = () => {
                            this.imageUrl = imageUrl;
                            this.imageLoading = false;
                        };
                        img.onerror = () => {
                            this.imageError = '无法加载图片，可能文件已被删除或路径不正确';
                            this.imageLoading = false;
                        };
                        img.src = imageUrl;

                    } catch (error) {
                        console.error('预览图片失败:', error);
                        this.imageError = '预览图片失败: ' + error.message;
                        this.imageLoading = false;
                    }
                },
                formatFileSize(bytes) {
                    if (!bytes) return '0 B';
                    const k = 1024;
                    const sizes = ['B', 'KB', 'MB', 'GB'];
                    const i = Math.floor(Math.log(bytes) / Math.log(k));
                    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
                }
            }
        }).mount('#app');
    </script>

    <style>
        /* 分页样式优化 */
        .pagination .page-item.active .page-link {
            background-color: #007bff !important;
            border-color: #007bff !important;
            color: #ffffff !important;
            font-weight: bold;
        }
        
        .pagination .page-item.active .page-link:hover {
            background-color: #0056b3 !important;
            border-color: #0056b3 !important;
            color: #ffffff !important;
        }
        
        .pagination .page-link {
            color: #007bff;
            border: 1px solid #dee2e6;
            padding: 0.375rem 0.75rem;
            margin: 0 2px;
            border-radius: 0.375rem;
            transition: all 0.2s ease-in-out;
        }
        
        .pagination .page-link:hover {
            color: #0056b3;
            background-color: #e9ecef;
            border-color: #dee2e6;
        }
        
        .pagination .page-item.disabled .page-link {
            color: #6c757d;
            background-color: #fff;
            border-color: #dee2e6;
        }
        
        .pagination .page-item.disabled .page-link:hover {
            color: #6c757d;
            background-color: #fff;
            border-color: #dee2e6;
        }
        
        /* 分页大小选择器样式 */
        .form-select-sm {
            border-radius: 0.375rem;
            border: 1px solid #ced4da;
            transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
        }
        
        .form-select-sm:focus {
            border-color: #86b7fe;
            outline: 0;
            box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
        }
    </style>
</body>
</html>
